/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package proyecto;

/**
 *
 * @author Luis Romero
 */
import java.util.logging.Logger;
import java.util.logging.Level;
import static proyecto.Constantes.*;

public class WB extends Thread {

    SharedMem MInt;
    Mem ANT;
    IF SIG;
    Registros Reg;
    boolean repite;
    final Object lock;
    Nucleo n;
    Reloj reloj;

    public WB(Registros r) {
        Reg = r;
        MInt = new SharedMem();
        this.setName("WB");
        repite = true;
        lock = new Object();
    }

    public void setEtapas(Mem m,IF fetch) {
        ANT = m;
        SIG = fetch;
    }
    
    public void setReloj(Reloj reloj){
        this.reloj = reloj;
    }

    public void parar() {
        synchronized (lock) {
            try {
               // System.out.println("Parar WB");
                lock.wait();
                
            } catch (InterruptedException ex) {
                Logger.getLogger(ID.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void seguir() {
        synchronized (lock) {
            lock.notify();
            //System.out.println("Seguir WB");
        }
    }

    public void setNucleoP(Nucleo N){
        n=N;
    }

    public synchronized void liberarRegistro(int r, int value){
       // System.out.println("Voy para validar:" + r);
        Reg.validarRegistro(r);
       // System.out.println("Liberando Registro "+r);
        Reg.setRegistro(r, value);
       // System.out.println("Libre Registro "+r);
        
    }

    private synchronized void generarInterrupcion(){
        //Una interrupcion guarda los registros en memoria principal
        // luego recibe el espacio en donde inician los registros
        //y luego lo mete en la cola con el PC de donde quedo
        int mio = n.MP.AlmacenarRegistros(Reg);
        n.C.colaHilos.mete(mio, MInt.getReg(NPC));
    }

    public void run() {
        System.out.println("Inicio WB");
        n.seguir();
        this.parar();
        while (repite) {
            //n.seguir();
            //this.parar();
            System.out.println("WB: "+MInt.getReg(INST)+MInt.getReg(REGF1)+MInt.getReg(REGF2)+MInt.getReg(REGD));
            switch (MInt.getReg(INST)) {
                case DADDI:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(ALUOUT));
                    break;
                case DADD:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(ALUOUT));
                    break;
                case DSUB:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(ALUOUT));
                    break;
                case DMUL:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(ALUOUT));
                    break;
                case DDIV:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(ALUOUT));
                    break;
                case LW:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(LMD));
                    break;
                case SW:
                    //liberarRegistro(MInt.getReg(REGD), MInt.getReg(LMD));
                    break;
                case BEQZ:
                    break;
                case BNEZ:
                    break;
                case JAL:
                    break;
                case JR:
                    break;
                case LL:
                    liberarRegistro(MInt.getReg(REGD), MInt.getReg(LMD));
                    liberarRegistro(32, MInt.getReg(ALUOUT));
                    break;
                case SC:
                    liberarRegistro(MInt.getReg(REGD), 1);
                    break;
                case FIN:
                    repite = false;
                    break;
                case INTERRUPT:
                    this.generarInterrupcion();
                    repite = false;
                    break;
                default:
                    break;
            }
            //this.parar();
           // SIG.seguir();
            reloj.cuentaHilo(4);
            reloj.seguir();
            
            if(repite){
                ANT.seguir();
                //SIG.seguir();
                this.parar();
               
            }else{
                ANT.seguir();
            }
            System.out.println("Fin de ejecución de la instruccion: "+MInt.getReg(INST)+MInt.getReg(REGF1)+MInt.getReg(REGF2)+MInt.getReg(REGD));
        }
        ANT.seguir();
        //n.seguir();
        System.out.println("Murio WB");
    }
}
